package jcu.sal.agent.netty;

import static org.jboss.netty.channel.Channels.write;

import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;

import jcu.sal.common.Response;
import jcu.sal.common.StreamID;
import jcu.sal.common.agents.netty.NettyConstants;
import jcu.sal.common.events.Event;

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipelineCoverage;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;

/**
 * @author Marc Hammerton
 * 
 */
@ChannelPipelineCoverage("all")
public class NettyAgentMessageEncoder extends SimpleChannelHandler {

	@Override
	public void writeRequested(ChannelHandlerContext chx, MessageEvent e)
			throws Exception {

		ChannelBuffer buf = ChannelBuffers.dynamicBuffer();

		if (e.getMessage() instanceof String) {
			byte[] data = ((String) e.getMessage()).getBytes();

			buf.writeShort(NettyConstants.RESP_SYNC_STRING);
			buf.writeInt(data.length);
			buf.writeBytes(data);
		} else if(e.getMessage() instanceof StreamID) {
			StreamID id = (StreamID) e.getMessage();
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			ObjectOutputStream oos = new ObjectOutputStream(bos);
			oos.writeObject(id);
			oos.flush();
			oos.close();
			bos.close();
			byte[] idData = bos.toByteArray();
			
			buf.writeShort(NettyConstants.RESP_SYNC_STREAMID);
			buf.writeInt(idData.length);
			buf.writeBytes(idData);
		} else if(e.getMessage() instanceof Response) {
			Response response = (Response) e.getMessage();
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			ObjectOutputStream oos = new ObjectOutputStream(bos);
			oos.writeObject(response);
			oos.flush();
			oos.close();
			bos.close();
			byte[] responseData = bos.toByteArray();
			
			buf.writeShort(NettyConstants.RESP_ASYNC_RESPONSE);
			buf.writeInt(responseData.length);
			buf.writeBytes(responseData);
		} else if(e.getMessage() instanceof Event) {
			Event event = (Event) e.getMessage();
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			ObjectOutputStream oos = new ObjectOutputStream(bos);
			oos.writeObject(event);
			oos.flush();
			oos.close();
			bos.close();
			byte[] eventData = bos.toByteArray();
			
			buf.writeShort(NettyConstants.RESP_ASYNC_EVENT);
			buf.writeInt(eventData.length);
			buf.writeBytes(eventData);
			eventData = null;
		}
		
		// Send the constructed message.
		write(chx, e.getChannel(), e.getFuture(), buf, e.getRemoteAddress());
	}
}
